﻿module ManualRenderTests


open System.Windows.Controls
open NUnit.Framework
open Dom
open HtmlDom
open Controls
open DocumentHost
open DummyHost
open DocumentFactory
open Layout
open MockDisplayElements
open Rendering
open RenderingContext


let showWindow (action:( System.Windows.Window -> unit )) (title:string) =
    let t = System.Threading.Thread(fun () ->  
        let window = System.Windows.Window()
        window.Title <- title
        window.Width <- 400.0
        // Initiates the dispatcher thread shutdown when the window closes
        window.Closed.Add(fun _ -> do window.Dispatcher.InvokeShutdown())
        window.Show();
        action(window)

        // Makes the thread support message pumping
        System.Windows.Threading.Dispatcher.Run();
    )
    t.SetApartmentState(System.Threading.ApartmentState.STA)
    t.Start()
    t.Join()   


let showWindowVisualHost (draw:VisualHostControl -> unit) (titel:string) =    
    let init (window1:System.Windows.Window) =
        let canvas = ScrollViewer()
        window1.Content <- canvas   
        let vhc = VisualHostControl()        
        do canvas.Content <- vhc
        draw vhc 

    showWindow init titel

let showWindowDrawing (draw:System.Windows.Media.DrawingContext -> unit) (titel:string) =    
    let init (host:VisualHostControl) =
        let drawingVisual = System.Windows.Media.DrawingVisual();            
        host.AddVisual(drawingVisual)
        let drawingContext = drawingVisual.RenderOpen();
        draw drawingContext
        drawingContext.Close()       

    showWindowVisualHost init titel

let renderInWindow (titel:string) (elem:SElement) =
    let draw (drawingContext:System.Windows.Media.DrawingContext)  =
        let layout = layoutRoot elem 400
        let rx = RenderingContext(drawingContext, System.Windows.Point(0.0,0.0))
        renderLayout ((0,0),layout) rx

    showWindowDrawing draw titel  


[<TestFixture>]
type testRenderLayouts() = 

    [<Test>]
    member self.testRender() =
        let elem = SElement("", [SText("abcd abcd")])
        renderInWindow "One line text" elem

    [<Test>]
    member self.renderRedText() =
        let elem = SElement("", [SText("color:red", "abcd abcd")])
        renderInWindow "Red text" elem

    [<Test>]
    member self.renderInlineBlock() =
        let elem = SElement("", [
                                    SText("abcd abcd")
                                    SElement("display:inline-block;border-color:black;border-width:2px;margin:2px;padding:2px;", [SText("abcd abcd")])
                                    SText("abcd abcd abcd abcd abcd abcd abcd")
                                    ])
        renderInWindow "Inline block" elem


    [<Test>]
    member self.renderLineBreak2() =
        renderInWindow "Two lines"  
            (SElement("", [SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd")]))

    [<Test>]
    member self.renderWidth() =
        renderInWindow "Narrow block" 
            (SElement("width:200px;border-color:black;border-width:2px", 
                [
                    SText("abcde abcde abcde abcde abcde abcde abcde abcde abcde abcde")]))

    [<Test>]
    member self.renderFloatLeft() =
        let elem = SElement("", [SElement("float:left;border-color:black;border-width:2px",[SText("color:red", "xyz")]);SText("abcd abcd abcd")])
        renderInWindow "Float left" elem  

    [<Test>]
    member self.renderFloatLeftMultiline() =
        let elem = SElement("", 
                    [
                        SElement("float:left;border-color:black;border-width:2px;width:100px",[SText("color:red", "xyzq xyzq xyzq")]);
                        SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd")])
        renderInWindow "Float left" elem  

    [<Test>]
    member self.renderFloatLeftNextLine() =
        let elem = SElement("", 
                    [
                        SText("abcd abcd abcd abcd abcd x")
                        SElement("float:left;width:200;border-color:black;border-width:2px",[SText("color:red", "xyz")])
                        SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd")
                    ])
        renderInWindow "Float left moved to next line" elem  


    [<Test>]
    member self.renderFloatLeft2() =
        let elem = SElement("", 
                    [
                        SElement("float:left;border-color:black;border-width:2px", [SText("color:red", "xyz")])
                        SText("abcd abcd abcd")
                        SElement("float:left;border-color:black;border-width:2px", [SText("color:blue", "xyz")])
                        SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd")
                        ])
        renderInWindow "Two left floats" elem  

    [<Test>]
    member self.renderFloatLeft3() =
        let elem = SElement("", 
                    [
                        SElement("float:left;border-color:black;border-width:2px;width:250px;", [SText("color:red", "xyz")])
                        SText("abcd x")
                        SElement("float:left;border-color:black;border-width:2px;width:250px;", [SText("color:blue", "xyz")])
                        SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd")
                     ])
        renderInWindow "Two left floats wide" elem 

    [<Test>]
    member self.renderFloats() =
        let elem = SElement("width:300px;border-color:red;border-width:1px;", 
                    [
                        SElement("float:left;border-color:black;border-width:2px;height:100px", [SText("asdf")])
                        SElement("float:left;border-color:black;border-width:2px;height:50px", [SText("asdf")])
                        SElement("float:left;border-color:black;border-width:2px", [SText("asdf")])
                        SElement("float:right;border-color:black;border-width:2px", [SText("asdf asdf asdf")])
                        SElement("float:left;border-color:black;border-width:2px", [SText("asdf asdf asdf")])
                        SElement("float:right;border-color:black;border-width:2px", [SText("asdf")])
                    ])
        renderInWindow "Multiple floats" elem 

    [<Test>]
    member self.renderFloatRight() =
        let elem = SElement("width:300px;border-color:grey;border-width:1px", 
                    [
                        SText("abcd abcd x")
                        SElement("float:right;border-color:black;border-width:2px",[SText("color:red", "xyzq xyzq")])
                        SText("abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd")
                    ])
        renderInWindow "Float right" elem  

    [<Test>]
    member self.renderTable() =
        let elem = SElement("display:table;border-width:4px;border-color:black", 
                    [
                        SElement("display: table-row",
                            [
                                SElement("display: table-cell;background-color:green;padding:4px;",[SText("", "abcd")])
                                SElement("display: table-cell;background-color:yellow",[SText("", "abcd abcd abcd abcd abcd abcd abcd abcd")])
                            ])
                        SElement("display: table-row",
                            [
                                SElement("display: table-cell",[SText("", "abcd ijk")])
                                SElement("display: table-cell",[SText("", "efgh")])
                            ])
                    ])
        renderInWindow "Table" elem  

    [<Test>]
    member self.renderPre() =
        let elem = SElement("",
                    [SText("text-wrap: none;text-space-collapse: preserve;font-family: 'courier new';", "   abcd   \n    asdf  Asdf 2 + 2 ")])
        renderInWindow "Pre" elem

    /// Draw graphics to a window.
    [<Test>][<Ignore("UI")>]
    member self.testDraw() =
        let draw (drawingContext:System.Windows.Media.DrawingContext)  =

            // Create a rectangle and draw it in the DrawingContext.
            let rect = System.Windows.Rect(System.Windows.Point(0.0, 0.0), System.Windows.Size(320.0, 80.0));
            drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, null, rect);

            // circle         
            let mySolidColorBrush = System.Windows.Media.SolidColorBrush()
            let pen = System.Windows.Media.Pen(mySolidColorBrush, 10.0)
            drawingContext.DrawEllipse(System.Windows.Media.Brushes.CornflowerBlue, pen, System.Windows.Point(0.0,0.0), 100.0, 100.0)
            
        showWindowDrawing draw ""

